//////////////////////////////////////////////////////////////////////////
//
// This file is a part of APNS provider project.
// Copyright (c) Vladimir Gumenuk, 2013-2014.
//
// PROJECT:         APNS provider
// FILE:            gmslib.h - gms utility library
// AUTHOR:          Vladimir Gumenuk
// DATE:            22-Dec-2013
// MODIFICATIONS:
//
//////////////////////////////////////////////////////////////////////////

#ifndef __gmslib_h__
#define __gmslib_h__

//////////////////////////////////////////////////////////////////////////
// IBuffer
interface IGMSBuffer : public IUnknown
{
    STDMETHOD_(DWORD,GetSize)() PURE;
    STDMETHOD_(const LPBYTE, GetPtr)() PURE;
    STDMETHOD(Add)( const LPBYTE pBuf, DWORD dwSize ) PURE;
    STDMETHOD(AddBYTE)( BYTE Val ) PURE;
    STDMETHOD(Attach)( LPBYTE pBuf, DWORD dwSize ) PURE;
};

HRESULT __stdcall CreateGMSBuffer( IGMSBuffer **ppOut );

//////////////////////////////////////////////////////////////////////////
// GMS Network
//////////////////////////////////////////////////////////////////////////
//! Flags for valid fields
#define NPF_COMMAND      0x00000001
#define NPF_IDENT        0x00000002
#define NPF_SESSIONID    0x00000004
#define NPF_TIME         0x00000008
#define NPF_IP           0x00000010
#define NPF_PORT         0x00000020
#define NPF_CRYPTOKEY    0x00000040
#define NPF_DATASIZE     0x00000080
#define NPF_DATATYPE     0x00000100
#define NPF_DATA         0x00000200

//! Flags for data type
#define NPDT_BINARY      0x00000001
#define NPDT_OBJECT      0x00000002

//! Size definitions
#define NP_CMD_SIZE         64
#define NP_RUBBISH_SIZE     32
#define NP_IDENT_SIZE       64
#define NP_IP_SIZE          32
#define NP_CRYPTOKEY_SIZE   256

interface IGMSNetClient : public IUnknown
{
    STDMETHOD(Connect)( /*[in]*/LPCOLESTR lpstrAddr, /*[in]*/DWORD dwPort ) PURE;
    STDMETHOD(Disconnect)() PURE;
    STDMETHOD(Send)( IGMSBuffer *pBuffer ) PURE;
    STDMETHOD(Receive)( IGMSBuffer **pBuffer ) PURE;
    STDMETHOD_(int,SendRaw)( LPBYTE pBuffer, DWORD dwSize ) PURE;
    STDMETHOD_(int,ReceiveRaw)( LPBYTE pBuffer, DWORD dwSize ) PURE;
    STDMETHOD_(BOOL,IsConnected)() PURE;
    STDMETHOD(GetRemoteHostName)( WCHAR szBuf[MAX_PATH] ) PURE;
    STDMETHOD(GetRemoteIP)( ULONG *pulIP ) PURE;
    STDMETHOD(GetRemoteIP)( char szBuf[NP_IP_SIZE] ) PURE;
    STDMETHOD(GetLocalIP)( ULONG *pulIP ) PURE;
    STDMETHOD(GetLocalIP)( char szBuf[NP_IP_SIZE] ) PURE;
    STDMETHOD_(DWORD, IsDataAvailable)() PURE;
};

interface IGMSNetListener : public IUnknown
{
    STDMETHOD(Listen)( IGMSNetClient **ppClient ) PURE;
    STDMETHOD(CancelListen)() PURE;
};

interface IGMSNetwork : public IUnknown
{
    STDMETHOD(InitNetLayer)() PURE;
    STDMETHOD(ShutNetLayer)() PURE;
    STDMETHOD(CreateNetClient)( IGMSNetClient **ppClient ) PURE;
    STDMETHOD(CreateNetListener)( DWORD dwPort, IGMSNetListener **ppListener ) PURE;
};

HRESULT __stdcall CreateGMSNetwork( IGMSNetwork **ppNet );


//////////////////////////////////////////////////////////////////////////
// guids

extern "C" const IID IID_IGMSBuffer;
extern "C" const IID IID_IGMSNetwork;
extern "C" const IID IID_IGMSNetClient;
extern "C" const IID IID_IGMSNetListener;

// {0CEEDC29-570A-4b0c-BEFE-D2DD29064FFB}
DEFINE_GUID(IID_IGMSBuffer, 
    0xceedc29, 0x570a, 0x4b0c, 0xbe, 0xfe, 0xd2, 0xdd, 0x29, 0x6, 0x4f, 0xfb);

// {526DAF67-B095-44fa-A069-98E92421CD30}
DEFINE_GUID(IID_IGMSNetwork, 
    0x526daf67, 0xb095, 0x44fa, 0xa0, 0x69, 0x98, 0xe9, 0x24, 0x21, 0xcd, 0x30);

// {42052FEC-11B3-46fe-BD97-7D7C106926C9}
DEFINE_GUID(IID_IGMSNetClient, 
    0x42052fec, 0x11b3, 0x46fe, 0xbd, 0x97, 0x7d, 0x7c, 0x10, 0x69, 0x26, 0xc9);

// {C112150B-114A-4a22-BE28-8080CD2F8B39}
DEFINE_GUID(IID_IGMSNetListener, 
    0xc112150b, 0x114a, 0x4a22, 0xbe, 0x28, 0x80, 0x80, 0xcd, 0x2f, 0x8b, 0x39);

//////////////////////////////////////////////////////////////////////////

#define SAFE_DELETE(x) {if(x){delete x;x=NULL;}}
#define SAFE_DELETE_ARRAY(x) {if(x){delete []x;x=NULL;}}
#define SAFE_FREE(x) {if(x){free(x);x=NULL;}}
#define SAFE_RELEASE(x) {if(x){x->Release();x=NULL;}}

//////////////////////////////////////////////////////////////////////////
// Logging API
#define LOG1 LogPrint1
#define LOG2 LogPrint2
#define LOG3 LogPrint3

BOOL LogOpen( LPCTSTR lpstrFileName );
void LogClose();
void LogSetLevel( int iLevel );
void LogEnableDbgTrace( BOOL bEnable );
void LogPrint1( LPCTSTR lpstrFmt, ... );
void LogPrint2( LPCTSTR lpstrFmt, ... );
void LogPrint3( LPCTSTR lpstrFmt, ... );
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// DATE constants:
#define DATE_1_MINUTE   (0.000694444)
#define DATE_2_MINUTES  (0.001388888)
#define DATE_5_MINUTES  (0.003472222)
#define DATE_10_MINUTES (0.006944444)
#define DATE_11_MINUTES (0.0078125)
#define DATE_22_MINUTES (0.015625)
#define DATE_45_MINUTES (0.03125)
#define DATE_1_HOUR     (0.041666666)
#define DATE_1_5_HOURS  (0.0625)
#define DATE_2_HOURS    (0.083333333)
#define DATE_3_HOURS    (0.125)


#define WM_NET_CLIENT_EXITED (WM_USER+1001)

// Errors
#define GMSLIBERRORBASE 4096
#define E_GMS_TIMEOUT               MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, GMSLIBERRORBASE+1)
#define E_GMS_INVALIDPACKETSIZE     MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, GMSLIBERRORBASE+2)
#define E_GMS_INVALIDPACKET         MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, GMSLIBERRORBASE+3)
#define E_GMS_ENCRYPT               MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, GMSLIBERRORBASE+4)
#define E_GMS_DECRYPT               MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, GMSLIBERRORBASE+5)
#define E_GMS_COMPRESS              MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, GMSLIBERRORBASE+6)
#define E_GMS_DECOMPRESS            MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, GMSLIBERRORBASE+7)



#endif // __gmslib_h__